import { defaultEquals, IEqualsFunction } from "../utils";
import {Node} from './linked-list-models';

export default class LinkedList<T>{
    protected count = 0;
    protected head:Node<T> | undefined;
    constructor(protected equalsFn:IEqualsFunction<T>=defaultEquals){}
    /**
     * 添加一个元素
     * @param element <T>
     */
    push(element:T){
        const node = new Node(element);
        let current;
        if(this.head == null){
            this.head = node;
        }else{
            current = this.head;
            while(current.next != null){
                current = current.next;
            }
            current.next = node
        }
        this.count++;
    }
    /**
     * 返回链表特定位置的元素
     * @param index number 索引值
     */
    getElementAt(index: number) {
        if (index >= 0 && index <= this.count) {
          let node = this.head;
          for (let i = 0; i < index && node != null; i++) {
            node = node.next;
          }
          return node;
        }
        return undefined;
    }
    /**
     * 向链表的特定位置插入一个新元素
     * @param element 元素值
     * @param index 索引值
     */
    insert(element: T, index: number) {
        if (index >= 0 && index <= this.count) {
          const node = new Node(element);
    
          if (index === 0) {
            const current = this.head;
            node.next = current;
            this.head = node;
          } else {
            const previous = this.getElementAt(index - 1);
            node.next = previous!.next
            previous!.next = node.next;
          }
          this.count++;
          return true;
        }
        return false;
      }
    /**
     * 从链表的特定位置移除一个元素
     * @param index 索引值
     */
    removeAt(index: number) {
        if (index >= 0 && index < this.count) {
          let current = this.head;
    
          if (index === 0) {
            this.head = current!.next;
          } else {
            const previous = this.getElementAt(index - 1);
            current = previous!.next;
            previous!.next = current!.next;
          }
          this.count--;
          return current!.element;
        }
        return undefined;
      }
    /**
     * 从链表中移除一个元素
     * @param element 元素
     */
    remove(element:T){
        const index = this.indexOf(element);
        return this.removeAt(index);
    }
    /**
     * 返回元素在链表中的索引
     * @param element 元素
     */
    indexOf(element:T){
        let current = this.head;
        for (let i=0;i<this.size()&&current!=null;i++) {
            if(this.equalsFn(element,current.element)){
                return i;
            }
            current = current.next
        }
        return -1;
    }
    isEmpty(){
        return this.size() === 0;
    }
    size(){
        return this.count;
    }
    getHead(){
        return this.head;
    }
    clear(){
        this.head = undefined;
        this.count = 0;
    }
    toString() {
        if (this.head == null) {
          return '';
        }
        let objString = `${this.head.element}`;
        let current = this.head.next;
        for (let i = 1; i < this.size() && current != null; i++) {
          objString = `${objString},${current.element}`;
          current = current.next;
        }
        return objString;
    }
}

